package br.usp.pcs.basys.engine;

import java.util.Comparator;
import java.util.Date;
import java.util.PriorityQueue;
import java.util.Queue;

import br.usp.pcs.basys.event.DiskRequest;
import br.usp.pcs.basys.event.Event;
import br.usp.pcs.basys.event.MemoryRequest;
import br.usp.pcs.basys.event.ProcessorRequest;

public class Resources implements IResources {
	private static IResources singleton;
	private Date simulationDate = new Date(0);
	private static Queue<Event> events;
	private static final ComputerResourceManager<Processor, ProcessorRequest> processorManager = new ComputerResourceManager<Processor, ProcessorRequest>();
	private static final ComputerResourceManager<Disk, DiskRequest> diskManager = new ComputerResourceManager<Disk, DiskRequest>();
	private static final ComputerResourceManager<Memory, MemoryRequest> memoryManager = new MemoryResourceManager();
	
	private Resources() {
	}

	static IResources getInstance() {
		if (singleton == null) {
			singleton = new Resources();
			Comparator<Event> comparator = new Comparator<Event>() {

				public int compare(Event o1, Event o2) {
					return o1.getDate().compareTo(o2.getDate());
				}

			};
			events = new PriorityQueue<Event>(35, comparator);
		}
		return singleton;
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#getSimulationDate()
	 */
	public Date getSimulationDate() {
		return simulationDate;
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#setSimulationDate(java.util.Date)
	 */
	public void setSimulationDate(Date simulationDate) {
		this.simulationDate = simulationDate;
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#allocate(long)
	 */
	public void allocate(long size) throws UnavaiableResourceException {
		((MemoryResourceManager)memoryManager).allocate(size);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#deallocate(long)
	 */
	public void deallocate(long size) {
		((MemoryResourceManager)memoryManager).deallocate(size);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#queue(br.usp.pcs.basys.event.MemoryRequest)
	 */
	public boolean queue(MemoryRequest e) {
		return memoryManager.queue(e);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#pollMemoryQueue()
	 */
	public MemoryRequest pollMemoryQueue() {
		return memoryManager.poll();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#add(br.usp.pcs.basys.event.Event)
	 */
	public boolean add(Event e) {
		return events.add(e);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#getNextEvent()
	 */
	public Event getNextEvent() {
		return events.poll();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#setMemory(br.usp.pcs.basys.engine.Memory)
	 */
	public void setMemory(Memory memory) {
		memoryManager.setResource(memory);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#releaseProcessor()
	 */
	public void releaseProcessor() {
		processorManager.release();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#reserveProcessor()
	 */
	public void reserveProcessor() throws UnavaiableResourceException {
		processorManager.reserve();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#releaseDisk()
	 */
	public void releaseDisk() {
		diskManager.release();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#reserveDisk()
	 */
	public void reserveDisk() throws UnavaiableResourceException {
		diskManager.reserve();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#queue(br.usp.pcs.basys.event.ProcessorRequest)
	 */
	public boolean queue(ProcessorRequest e) {
		return processorManager.queue(e);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#pollProcessorQueue()
	 */
	public ProcessorRequest pollProcessorQueue() {
		return processorManager.poll();
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#queue(br.usp.pcs.basys.event.DiskRequest)
	 */
	public boolean queue(DiskRequest e) {
		return diskManager.queue(e);
	}

	/* (non-Javadoc)
	 * @see br.usp.pcs.basys.engine.iResources#pollDiskQueue()
	 */
	public DiskRequest pollDiskQueue() {
		return diskManager.poll();
	}

}
